Special Variables

Variables in Common Lisp are lexically scoped by default, but it is still possible to have a kind of dynamically scoped variable called a special variable. There is no special evaltrace notation for dynamic variables; one simply notes whether a given name has been declared special or not, and once it has, all variables with that name will be dynamically scoped. By convention, special variable names are written with surrounding asterisks, so that they can be easily distinguished from lexical variable names. A variable name can be declared special with the DEFVAR form. Let's return to our earlier PARENT/CHILD example, but this time with a special variable.


\begin{code}
(defvar *n* 1000)
\strut
(defun parent (*n*)
(child (+ *n* 2)))
\strut
(defun child (p)
(list *n* p))
\end{code}

Figure: Evaltrace diagram illustrating Common Lisp's ``special'' variables.
\begin{figure}{\noindent\rule{\textwidth}{.01in}}
\par
\begin{evaltrace}
;{\it t...
...1000}
\end{evaltrace}\par\par
{\noindent\rule{\textwidth}{.01in}}
\end{figure}

An evaltrace of PARENT is given in Figure [*]. The evaluation rule for dynamically scoped variables is that we search all the enclosing contours in the order they appear on the call stack, ignoring the contours' pointers to their normal (lexical) parents. The top level dynamic value is used only if we make it all the way out to the global contour, meaning that no other contour presently has a variable with the same name. PARENT ``rebinds'' the special variable *N*, meaning that it establishes a (temporary) new dynamic variable with the name *N* that lasts as long as PARENT remains on the call stack. Dynamic variables cannot be maintained in closures, since they are entirely dependent on the call stack. PARENT's binding of a variable *N* with value 3 is in effect when CHILD evaluates *N*, so that is the variable that CHILD sees. When PARENT exits, its binding of *N* disappears, and thus the previous binding of *N* becomes visible again.